package com.github.icloudpay.crm.core.biz;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.github.icloudpay.crm.core.entity.Consumer;
import com.github.icloudpay.crm.core.entity.MerchantAccount;
import com.github.icloudpay.crm.core.entity.PersonalAccount;
import com.github.icloudpay.crm.core.mapper.ConsumerMapper;
import com.github.icloudpay.crm.core.mapper.MerchantAccountMapper;
import com.github.icloudpay.crm.core.mapper.PersonalAccountMapper;
import com.github.wxiaoqi.security.auth.common.util.SnowFlake;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.common.msg.ResponseCode;
import com.github.wxiaoqi.security.common.util.MD5;

/**
 * 个人账户(冻结账户准入不准出)
 * @author centerroot
 * @email lfw6699@163.com
 * @date 2018-05-25 15:20:48
 */
@Service
public class PersonalAccountBiz extends BaseBiz<PersonalAccountMapper,PersonalAccount> {
	private static final Logger logger = LoggerFactory.getLogger(PersonalAccountBiz.class);
	
	@Autowired
	private ConsumerMapper consumerMapper;
	@Autowired
	private PersonalAccountMapper personalAccountMapper;
	@Autowired
	private MerchantAccountMapper merchantAccountMapper;
	@Value("${bountyHunter.balanceSaltValue}")
	private String balanceSaltValue;
	
	/**
	 * 个人账户开户
	 * 成功返回账户号
	 * @param customerAccount
	 */
	public Map<String, Object> openAccount(Map<String, Object> param){
		logger.info("个人账户开户   请求参数：{}",param);
		Map<String, Object> respMap = new HashMap<String, Object>();
		String perId = (String) param.get("perId");
		String accType = (String) param.get("accType");
		List<PersonalAccount> perAccList = personalAccountMapper.queryPersonalAccount(param);
		PersonalAccount personalAccount = new PersonalAccount();
		if (null == perAccList || perAccList.size() <= 0) {
			String accId = String.valueOf(SnowFlake.getId());
			personalAccount.setAccId(accId);
			personalAccount.setAccBalance(BigDecimal.ZERO);
			personalAccount.setChecksum(MD5.sign(personalAccount.getAccBalance().toString(), balanceSaltValue, "utf-8"));
			personalAccount.setCcy("CNY");
			personalAccount.setPerId(perId);
			personalAccount.setAccType(accType);
			personalAccount.setCreatetime(new Timestamp(System.currentTimeMillis()));
			personalAccountMapper.insert(personalAccount);
		}else{
			personalAccount = perAccList.get(0);
		}
		respMap.put("personalAccount", personalAccount);
		respMap.put("code", ResponseCode.OK.getCode());
		respMap.put("msg", ResponseCode.OK.getMessage());
		logger.info("个人账户开户   响应参数：{}",respMap);
		return respMap;
	}
	
	/**
	 * 个人账户入金
	 * @param customerAccount
	 */
	public Map<String, Object> deposit(Map<String, Object> param){
		logger.info("个人账户入金   请求参数：{}",param);
		Map<String, Object> respMap = new HashMap<String, Object>();
		BigDecimal intoAmt = (BigDecimal) param.get("intoAmt");
		List<PersonalAccount> perAccList = personalAccountMapper.queryPersonalAccount(param);
		PersonalAccount personalAccount = new PersonalAccount();
		if (null != perAccList && perAccList.size() > 0) {
			personalAccount = perAccList.get(0);
			boolean flag = MD5.verify(personalAccount.getAccBalance().toString(), personalAccount.getChecksum(), balanceSaltValue, "utf-8");
			if (flag) {
				personalAccount.setAccBalance(personalAccount.getAccBalance().add(intoAmt));
				personalAccount.setChecksum(MD5.sign(personalAccount.getAccBalance().toString(), balanceSaltValue, "utf-8"));
				personalAccountMapper.updateByPrimaryKey(personalAccount);
				respMap.put("code", ResponseCode.OK.getCode());
				respMap.put("msg", ResponseCode.OK.getMessage());
			}else{
				respMap.put("code", ResponseCode.VERIFY_ACC_AMT.getCode());
				respMap.put("msg", ResponseCode.VERIFY_ACC_AMT.getMessage());
			}
		}else{
			respMap.put("code", ResponseCode.CUST_ACC_NOTEXIST.getCode());
			respMap.put("msg", ResponseCode.CUST_ACC_NOTEXIST.getMessage());
		}
		
		logger.info("个人账户入金   响应参数：{}",respMap);
		return respMap;
	}
	
	/**
	 * 个人账户出金
	 * @param customerAccount
	 */
	public Map<String, Object> withdraw(Map<String, Object> param){
		logger.info("个人账户出金   请求参数：{}",param);
		Map<String, Object> respMap = new HashMap<String, Object>();
		BigDecimal outAmt = (BigDecimal) param.get("outAmt");
		List<PersonalAccount> perAccList = personalAccountMapper.queryPersonalAccount(param);
		PersonalAccount personalAccount = new PersonalAccount();
		if (null != perAccList && perAccList.size() > 0) {
			personalAccount = perAccList.get(0);
			if ("00".equals(personalAccount.getAccountStatus())) {
				// 个人转出账户正常
				boolean flag = MD5.verify(personalAccount.getAccBalance().toString(), personalAccount.getChecksum(), balanceSaltValue, "utf-8");
				if (flag) {
					if (personalAccount.getAccBalance().compareTo(outAmt) >= 0) {
						personalAccount.setAccBalance(personalAccount.getAccBalance().subtract(outAmt));
						personalAccount.setChecksum(MD5.sign(personalAccount.getAccBalance().toString(), balanceSaltValue, "utf-8"));
						personalAccountMapper.updateByPrimaryKey(personalAccount);
						respMap.put("code", ResponseCode.OK.getCode());
						respMap.put("msg", ResponseCode.OK.getMessage());
					} else {
						respMap.put("code", ResponseCode.ACC_BALANCE_INSUFFICIENT.getCode());
						respMap.put("msg", ResponseCode.ACC_BALANCE_INSUFFICIENT.getMessage());
					}
				}else{
					respMap.put("code", ResponseCode.VERIFY_ACC_AMT.getCode());
					respMap.put("msg", ResponseCode.VERIFY_ACC_AMT.getMessage());
				}
			} else if("01".equals(personalAccount.getAccountStatus())) {
				// 个人转出账户被冻结
				respMap.put("code", ResponseCode.CUST_ACC_FREEZE.getCode());
				respMap.put("msg", ResponseCode.CUST_ACC_FREEZE.getMessage());
			}
		}else{
			respMap.put("code", ResponseCode.CUST_ACC_NOTEXIST.getCode());
			respMap.put("msg", ResponseCode.CUST_ACC_NOTEXIST.getMessage());
		}
		
		logger.info("个人账户出金   响应参数：{}",respMap);
		return respMap;
	}
	
	/**
	 * 系统内个人转账
	 * 转账给商家 intoConsumerAccType:00
	 * 转账给个人 intoConsumerAccType:01
	 * 1、判断转出账户是否存在
	 * 2、判断账户余额是否大于转出金额
	 * 3、判断转入用户是否存在
	 * 4、判断转入用户账户类型是企业还是个人
	 * 5、判断转入账户是否存在
	 * 6、转出账户余额减少，转入账户余额增多
	 * @param Map
	 */
	public Map<String, Object> transfer(Map<String, Object> param){
		logger.info("系统内个人转账   请求参数：{}",param);
		Map<String, Object> respMap = new HashMap<String, Object>();
		String perId = (String) param.get("perId");
		String intoMobile = (String) param.get("intoMobile");
		String intoConsumerAccType = (String) param.get("intoConsumerAccType");
		String accType = (String) param.get("accType");
		BigDecimal transferAmt = (BigDecimal) param.get("transferAmt");
		Map<String, Object> reqPerAccMap = new HashMap<String, Object>();
		reqPerAccMap.put("perId", perId);
		reqPerAccMap.put("accType", accType);
		List<PersonalAccount> perAccList = personalAccountMapper.queryPersonalAccount(reqPerAccMap);
		if (null != perAccList && perAccList.size() > 0) {
			PersonalAccount personalAccount = perAccList.get(0);
			if ("00".equals(personalAccount.getAccountStatus())) {
				// 个人转出账户正常
				boolean flag = MD5.verify(personalAccount.getAccBalance().toString(), personalAccount.getChecksum(), balanceSaltValue, "utf-8");
				if (flag) {
					if (personalAccount.getAccBalance().compareTo(transferAmt) >= 0) {
						Consumer consumer=consumerMapper.queryUserinfoByMobile(intoMobile);
						if (null != consumer) {
							if ("00".equals(intoConsumerAccType)) {
								if (null != consumer.getMerId()) {
									Map<String, Object> reqMerAccMap = new HashMap<String, Object>();
									reqMerAccMap.put("merId",  consumer.getMerId());
									reqMerAccMap.put("accType", accType);
									List<MerchantAccount> merchantAccounts = merchantAccountMapper.queryMerchantAccount(reqMerAccMap);
									if (null != merchantAccounts && merchantAccounts.size() > 0) {
										MerchantAccount merchantAccount = merchantAccounts.get(0);
										personalAccount.setAccBalance(personalAccount.getAccBalance().subtract(transferAmt));
										personalAccount.setChecksum(MD5.sign(personalAccount.getAccBalance().toString(), balanceSaltValue, "utf-8"));
										merchantAccount.setAccBalance(merchantAccount.getAccBalance().add(transferAmt));
										merchantAccount.setChecksum(MD5.sign(merchantAccount.getAccBalance().toString(), balanceSaltValue, "utf-8"));
										personalAccountMapper.updateByPrimaryKey(personalAccount);
										merchantAccountMapper.updateByPrimaryKey(merchantAccount);
										respMap.put("code", ResponseCode.OK.getCode());
										respMap.put("msg", ResponseCode.OK.getMessage());
									}else{
										respMap.put("code", ResponseCode.MER_ACC_NOTEXIST.getCode());
										respMap.put("msg", ResponseCode.MER_ACC_NOTEXIST.getMessage());
									}
								} else {
									respMap.put("code", ResponseCode.MER_NOTEXIST.getCode());
									respMap.put("msg", ResponseCode.MER_NOTEXIST.getMessage());
								}
							} else {
								if (null != consumer.getPerId()) {
									Map<String, Object> reqIntoPerAccMap = new HashMap<String, Object>();
									reqIntoPerAccMap.put("perId", consumer.getPerId());
									reqIntoPerAccMap.put("accType", accType);
									List<PersonalAccount> intoPerAccList = personalAccountMapper.queryPersonalAccount(reqIntoPerAccMap);
									if (null != intoPerAccList && intoPerAccList.size() > 0) {
										PersonalAccount intoPersonalAccount = intoPerAccList.get(0);
										personalAccount.setAccBalance(personalAccount.getAccBalance().subtract(transferAmt));
										personalAccount.setChecksum(MD5.sign(personalAccount.getAccBalance().toString(), balanceSaltValue, "utf-8"));
										intoPersonalAccount.setAccBalance(intoPersonalAccount.getAccBalance().add(transferAmt));
										intoPersonalAccount.setChecksum(MD5.sign(intoPersonalAccount.getAccBalance().toString(), balanceSaltValue, "utf-8"));
										personalAccountMapper.updateByPrimaryKey(personalAccount);
										personalAccountMapper.updateByPrimaryKey(intoPersonalAccount);
										respMap.put("code", ResponseCode.OK.getCode());
										respMap.put("msg", ResponseCode.OK.getMessage());
									}else{
										respMap.put("code", ResponseCode.MER_ACC_NOTEXIST.getCode());
										respMap.put("msg", ResponseCode.MER_ACC_NOTEXIST.getMessage());
									}
									
								} else {
									respMap.put("code", ResponseCode.CUST_ACC_NOTEXIST.getCode());
									respMap.put("msg", ResponseCode.CUST_ACC_NOTEXIST.getMessage());
								}
							}
						} else {
							respMap.put("code", ResponseCode.USER_NOTEXIST.getCode());
							respMap.put("msg", ResponseCode.USER_NOTEXIST.getMessage());
						}
					} else {
						respMap.put("code", ResponseCode.ACC_BALANCE_INSUFFICIENT.getCode());
						respMap.put("msg", ResponseCode.ACC_BALANCE_INSUFFICIENT.getMessage());
					}
				}else{
					respMap.put("code", ResponseCode.VERIFY_ACC_AMT.getCode());
					respMap.put("msg", ResponseCode.VERIFY_ACC_AMT.getMessage());
				}
			} else if("01".equals(personalAccount.getAccountStatus())) {
				// 个人转出账户被冻结
				respMap.put("code", ResponseCode.CUST_ACC_FREEZE.getCode());
				respMap.put("msg", ResponseCode.CUST_ACC_FREEZE.getMessage());
			}
			
		}else{
			respMap.put("code", ResponseCode.CUST_ACC_NOTEXIST.getCode());
			respMap.put("msg", ResponseCode.CUST_ACC_NOTEXIST.getMessage());
		}
		logger.info("系统内个人转账   响应参数：{}",respMap);
		return respMap;
	}
	
	
	/**
	 * 查询个人账户
	 * @param map
	 * @return
	 */
	public Map<String, Object> queryPersonalAccounts(Map<String, Object> map) {
		logger.info("查询个人账户参数。。。{}"+map);
		Map<String, Object> respMap = new HashMap<>();
		List<PersonalAccount> list = personalAccountMapper.queryPersonalAccount(map);
		logger.info("查询个人账户。。。{}"+list);
		respMap.put("accounts", list);
		return respMap;
	}
	
	
	/**
	 * 修改冻结状态
	 * @param map
	 * @return
	 */
	public Map<String, Object> updateAccountStatus(Map<String, Object> map) {
		logger.info("修改冻结状态参数。。。{}"+map);
		personalAccountMapper.updateAccountStatus(map);
		
		Map<String, Object> resp = new HashMap<>();
		return resp;
	}
	
	
	



}